001 /*
002 * Copyright (c) 2005 Stephen J. McConnell
003 *
004 * Licensed under the Apache License, Version 2.0 (the "License");
005 * you may not use this file except in compliance with the License.
006 * You may obtain a copy of the License at
007 *
008 * http://www.apache.org/licenses/LICENSE-2.0
009 *
010 * Unless required by applicable law or agreed to in writing, software
011 * distributed under the License is distributed on an "AS IS" BASIS,
012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
013 * implied.
014 *
015 * See the License for the specific language governing permissions and
016 * limitations under the License.
017 */
018
019 package net.dpml.metro.tools;
020
021 import java.io.File;
022 import java.io.FileOutputStream;
023 import java.io.IOException;
024
025 import net.dpml.tools.tasks.GenericTask;
026
027 import net.dpml.state.State;
028 import net.dpml.state.StateEncoder;
029
030 import org.apache.tools.ant.BuildException;
031
032 /**
033 * Task that handles the creation of an encoded state graph.
034 *
035 * @author <a href="http://www.dpml.net">Digital Product Meta Library</a>
036 * @version 1.1.0
037 */
038 public class StateTask extends GenericTask
039 {
040 private static final StateEncoder STATE_ENCODER = new StateEncoder();
041
042 private File m_output;
043 private String m_classname;
044 private StateDataType m_data;
045
046 StateDataType getData()
047 {
048 if( null == m_data )
049 {
050 m_data = new StateDataType( this, true );
051 }
052 return m_data;
053 }
054
055 /**
056 * Override the default output destination.
057 *
058 * @param file the overriding destination
059 */
060 public void setDest( File file )
061 {
062 m_output = file;
063 }
064
065 /**
066 * Override the class as the colocated destination.
067 *
068 * @param classname the classname of the target component.
069 */
070 public void setClass( String classname )
071 {
072 m_classname = classname;
073 }
074
075 /**
076 * Set the state name.
077 * @param name the cname of the state
078 */
079 public void setName( final String name )
080 {
081 getData().setName( name );
082 }
083
084 /**
085 * Mark the state as a terminal state.
086 * @param flag true if this is a terminal state
087 */
088 public void setTerminal( final boolean flag )
089 {
090 getData().setTerminal( flag );
091 }
092
093 /**
094 * Add a substate within the state.
095 * @return the sub-state datatype
096 */
097 public StateDataType createState()
098 {
099 return getData().createState();
100 }
101
102 /**
103 * Add an operation within this state.
104 * @return the operation datatype
105 */
106 public OperationDataType createOperation()
107 {
108 return getData().createOperation();
109 }
110
111 /**
112 * Add an interface within this state.
113 * @return the interface datatype
114 */
115 public InterfaceDataType createInterface()
116 {
117 return getData().createInterface();
118 }
119
120 /**
121 * Add an transition within this state.
122 * @return the operation datatype
123 */
124 public TransitionDataType createTransition()
125 {
126 return getData().createTransition();
127 }
128
129 /**
130 * Add an trigger to the state.
131 * @return the trigger datatype
132 */
133 public TriggerDataType createTrigger()
134 {
135 return getData().createTrigger();
136 }
137
138 /**
139 * Execute the task.
140 */
141 public void execute()
142 {
143 File file = getOutputFile();
144 File parent = file.getParentFile();
145 if( !parent.exists() )
146 {
147 parent.mkdirs();
148 }
149 createGraph( file );
150 }
151
152 /**
153 * Create an encoded state graph.
154 * @param file the output file
155 */
156 public void createGraph( File file )
157 {
158 try
159 {
160 FileOutputStream output = new FileOutputStream( file );
161 try
162 {
163 State graph = getData().getState();
164 STATE_ENCODER.export( graph, output );
165 }
166 catch( Exception e )
167 {
168 throw new BuildException( "State encoding error.", e );
169 }
170 finally
171 {
172 try
173 {
174 output.close();
175 }
176 catch( IOException ioe )
177 {
178 ioe.printStackTrace();
179 }
180 }
181 }
182 catch( BuildException e )
183 {
184 throw e;
185 }
186 catch( Exception e )
187 {
188 final String error =
189 "Internal error while attempting to build the graph.";
190 throw new BuildException( error, e, getLocation() );
191 }
192 }
193
194 private File getOutputFile()
195 {
196 if( null != m_output )
197 {
198 return m_output;
199 }
200 else if( null != m_classname )
201 {
202 File classes = getContext().getTargetClassesMainDirectory();
203 String path = m_classname.replace( '.', '/' );
204 String filename = path + ".xgraph";
205 return new File( classes, filename );
206 }
207 else
208 {
209 return getDefaultOutputFile();
210 }
211 }
212
213 /**
214 * Create and return the part output file.
215 * @return the part output file
216 */
217 protected File getDefaultOutputFile()
218 {
219 File deliverables = getContext().getTargetDeliverablesDirectory();
220 String type = State.TYPE;
221 String types = type + "s";
222 File dir = new File( deliverables, types );
223 String filename = getContext().getLayoutPath( type );
224 return new File( dir, filename );
225 }
226 }